home *** CD-ROM | disk | FTP | other *** search
Text File | 1996-02-20 | 16.8 KB | 487 lines | [TEXT/CWIE] |
- /*
- File: ResolveObjectSpecifier.cp
-
- Contains: xxx put contents here xxx
-
- Written by: Andy Nicholas, Greg Anderson, Chris Bingham, John Rohrlich, Max McFarland, Paul Ossenbruggen, Mike Kobb
-
- Copyright: © 1995 by Apple Computer, Inc., all rights reserved.
-
- <2> 9/18/95 ga
-
- */
-
-
- #include "ResolveObjectSpecifier.h"
- #include "AbstractScriptableObject.h"
- #include "Exceptions.h"
-
- #include <AEObjects.h>
-
-
- //----------------------------------------------------------------------------------------
- // ParseObjectSpecifier
- //----------------------------------------------------------------------------------------
- TAbstractObjectSpecifier* ParseObjectSpecifier(TDescriptor objectSpecifier, DescType desiredClassOfParent /*= typeNull*/, DescType keyFormOfParent /*= typeNull*/, TDescriptor* keyDataOfParent /*= nil*/)
- {
- TAbstractObjectSpecifier* result = nil;
-
- switch(objectSpecifier.DescriptorType())
- {
- case typeObjectSpecifier:
- {
- DescType desiredClass;
- DescType keyForm;
- TDescriptor keyData;
- TDescriptor containerDesc;
- TAbstractObjectSpecifier* containerSpec = nil;
-
- //
- // Extract the parameters from the object specifier
- //
- objectSpecifier.GetObjectSpecifierParameters(desiredClass, keyForm, &keyData, &containerDesc);
- containerSpec = ParseObjectSpecifier(containerDesc, desiredClass, keyForm, &keyData);
-
- //
- // At this point, if keyForm is formTest, then convert it
- // into a whose clause
- //
- if(keyForm == formTest)
- {
- TDescriptor testData(keyData);
- keyForm = formWhose;
- // take desiredClass, or use desiredClassOfParent?
-
- //
- // If we can collapse the parent specifier into the
- // formTest, then do so. The reason we do this is
- // for performance; if the request is "first item of ... whose",
- // without collapsing we would first get every
- // item whose, then extract just the first item.
- // With collapsing, we can stop searching after we
- // get the first match.
- //
- // n.b. The object support library collapses the
- // two specifiers together in exactly the same way.
- //
- keyData.MakeAERecord();
- if(keyDataOfParent && ((keyFormOfParent == formAbsolutePosition) || (keyFormOfParent == formRange)))
- {
- //
- // Note: At this point, the object support library would
- // convert the formRange descriptor into a simpler descriptor
- // of type typeWhoseRange, a coerced record that contains parameters
- // keyAEWhoseRangeStart and keyAEWhoseRangeStop. The formRange
- // descriptor is very similar, but it contains keyAERangeStart and
- // keyAERangeStop parameters, and they are object specifiers whose
- // key data contains the descriptors that should go into the
- // keyAEWhoseRangeStart and keyAEWhoseRangeStop parameters.
- // Rather than bother to extract these parameters at this point
- // and construct another similar descriptor, we instead do the
- // extraction when the descriptor is used.
- //
- // See TObjectCollector::TObjectCollector for details.
- //
- desiredClass = desiredClassOfParent;
- keyData.PutDescriptorParameter(keyAEIndex, *keyDataOfParent);
- keyDataOfParent->Dispose();
- }
- else
- {
- keyData.PutDescTypeParameter(keyAEIndex, kAEAll, typeAbsoluteOrdinal);
- }
- keyData.PutDescriptorParameter(keyAETest, testData);
- keyData.CoerceInPlace(typeWhoseDescriptor);
- }
-
- //
- // If our desiredClass, keyForm and keyData were rolled
- // into the whose clause formed in 'containerSpec', then
- // do not bother to create a specifier for it.
- //
- if((containerSpec != nil) && (containerSpec->KeyForm() == formWhose) && (keyData.DescriptorType() == typeNull))
- result = containerSpec;
- else
- result = new TObjectSpecifier(desiredClass, keyForm, keyData, containerSpec);
- break;
- }
-
- case typeObjectBeingExamined:
- result = new TObjectBeingExamined;
- break;
-
- case typeNull:
- result = nil;
- break;
-
- // typeAEList?
-
- default:
- result = new TArbitrarySpecifier(objectSpecifier);
- break;
- }
-
- return result;
- } // ParseObjectSpecifier
-
- //----------------------------------------------------------------------------------------
- // ResolveObjectSpecifier
- //----------------------------------------------------------------------------------------
- TTokenDescriptor ResolveObjectSpecifier(const TAETransaction& t, TDescriptor objectSpecifier, TDescriptor* objectThatCausedError)
- {
- TAbstractObjectSpecifier* parsedSpecifier = nil;
- TAbstractScriptableObject* result = nil;
- TTokenDescriptor resultToken;
- OSErr err = noErr;
-
- NOREGISTER(parsedSpecifier);
-
- Try
- {
- parsedSpecifier = ParseObjectSpecifier(objectSpecifier);
- if(parsedSpecifier == nil)
- FailErr(errAEEventFailed);
- result = parsedSpecifier->ResolveToken(t, nil, objectThatCausedError);
- if(result == nil)
- FailErr(errAENoSuchObject);
- resultToken.AdoptToken(result);
- }
- Catch(err)
- {
- delete parsedSpecifier;
- Throw(err);
- }
-
- return resultToken;
- } // ResolveObjectSpecifier
-
- //----------------------------------------------------------------------------------------
- // GetNullContainer
- //----------------------------------------------------------------------------------------
- TAbstractScriptableObject* GetNullContainer()
- {
- TTokenDescriptor nullContainerDesc = CreateNullContainerToken();
-
- return nullContainerDesc.TokenObject();
- } // GetNullContainer
-
- //========================================================================================
- // Class TAbstractObjectSpecifier
- //========================================================================================
-
- //----------------------------------------------------------------------------------------
- // TAbstractObjectSpecifier::~TAbstractObjectSpecifier
- //----------------------------------------------------------------------------------------
- TAbstractObjectSpecifier::~TAbstractObjectSpecifier()
- {
- }
-
- //----------------------------------------------------------------------------------------
- // TAbstractObjectSpecifier::KeyForm
- //----------------------------------------------------------------------------------------
- DescType TAbstractObjectSpecifier::KeyForm() const
- {
- return typeNull;
- }
-
- //----------------------------------------------------------------------------------------
- // TAbstractObjectSpecifier::RootContainerIsObjectBeingExamined
- //----------------------------------------------------------------------------------------
- Boolean TAbstractObjectSpecifier::RootContainerIsObjectBeingExamined() const
- {
- return false;
- }
-
- //----------------------------------------------------------------------------------------
- // TAbstractObjectSpecifier::ExtractParentSpecifier
- //----------------------------------------------------------------------------------------
- TAbstractObjectSpecifier* TAbstractObjectSpecifier::ExtractParentSpecifier(DescType& desiredClass, DescType& keyForm, TDescriptor& keyData)
- {
- desiredClass = typeNull;
- keyForm = typeNull;
- keyData.ClearDescriptor();
-
- return nil;
- }
-
- //========================================================================================
- // Class TObjectSpecifier
- //========================================================================================
-
- //----------------------------------------------------------------------------------------
- // TObjectSpecifier::~TObjectSpecifier
- //----------------------------------------------------------------------------------------
- TObjectSpecifier::~TObjectSpecifier()
- {
- fKeyData.Dispose();
- delete fContainer;
- if(fCachedToken != nil)
- fCachedToken->DisposeDesignator();
- } // TObjectSpecifier::~TObjectSpecifier
-
- //----------------------------------------------------------------------------------------
- // TObjectSpecifier::KeyForm
- //----------------------------------------------------------------------------------------
- DescType TObjectSpecifier::KeyForm() const
- {
- return fKeyForm;
- }
-
- //----------------------------------------------------------------------------------------
- // TObjectSpecifier::RootContainerIsObjectBeingExamined
- //----------------------------------------------------------------------------------------
- Boolean TObjectSpecifier::RootContainerIsObjectBeingExamined() const
- {
- if(fContainer == nil)
- return false;
- else
- return fContainer->RootContainerIsObjectBeingExamined();
- }
-
- //----------------------------------------------------------------------------------------
- // TObjectSpecifier::ExtractParentSpecifier
- //----------------------------------------------------------------------------------------
- TAbstractObjectSpecifier* TObjectSpecifier::ExtractParentSpecifier(DescType& desiredClass, DescType& keyForm, TDescriptor& keyData)
- {
- TAbstractObjectSpecifier* result = fContainer;
- desiredClass = fDesiredClass;
- keyForm = fKeyForm;
- keyData = fKeyData;
- fContainer = nil;
-
- return result;
- }
-
- //----------------------------------------------------------------------------------------
- // TObjectSpecifier::BuildObjectSpecifier
- //----------------------------------------------------------------------------------------
- TDescriptor TObjectSpecifier::BuildObjectSpecifier() const
- {
- TDescriptor result;
- TDescriptor fromContainer;
-
- if(fContainer)
- fromContainer = fContainer->BuildObjectSpecifier();
-
- //
- // If the key form of this specifier is 'typeWhoseDescriptor,' then we
- // need to build a test descriptor
- //
- if(fKeyForm == formWhose)
- {
- TDescriptor keyDataRecord = fKeyData.Coerce(typeAERecord);
-
- //
- // Extract keyAETest; this has most of the interesting data for the
- // "formTest" descriptor
- //
- TDescriptor testDesc = keyDataRecord.GetDescriptorParameter(keyAETest);
- result.MakeObjectSpecifier(fDesiredClass, fromContainer, formTest, testDesc, false);
- testDesc.Dispose();
-
- //
- // Extract keyAEIndex: if it's kAEAll, do nothing; otherwise make another
- // container ospec with MakeObjectSpecifier(fDesiredClass, result,
- // formAbsolutePosition or formRange, key data from keyAEIndex)
- //
- TDescriptor indexDesc = keyDataRecord.GetDescriptorParameter(keyAEIndex);
- if((indexDesc.DescriptorType() != typeAbsoluteOrdinal) || (indexDesc.GetDescTypeData(typeAbsoluteOrdinal) != kAEAll))
- {
- DescType formOfData = indexDesc.DescriptorType() == typeRangeDescriptor ? formRange : formAbsolutePosition;
-
- TDescriptor tempDesc = result;
- result.MakeObjectSpecifier(fDesiredClass, tempDesc, formOfData, indexDesc, false);
- tempDesc.Dispose();
- }
- indexDesc.Dispose();
- }
- else
- result.MakeObjectSpecifier(fDesiredClass, fromContainer, fKeyForm, fKeyData, false);
- fromContainer.Dispose();
-
- return result;
- } // TObjectSpecifier::BuildObjectSpecifier
-
- //----------------------------------------------------------------------------------------
- // TObjectSpecifier::ResolveToken
- //----------------------------------------------------------------------------------------
- TAbstractScriptableObject* TObjectSpecifier::ResolveToken(const TAETransaction& t, TAbstractScriptableObject* objectBeingExamined, TDescriptor* objectThatCausedError /*= nil*/) const
- {
- OSErr err = noErr;
-
- //
- // Don't bother to resolve this token if we've already done it
- // once--just use the object in the cache.
- //
- if((fCachedToken == nil) || (fCachedObjectBeingExamined != objectBeingExamined))
- {
- //
- // First step: recursively resolve our container token, so
- // we know who to ask to resolve the data in this specifier
- //
- TAbstractScriptableObject* containerToken = nil;
- if(fContainer == nil)
- containerToken = GetNullContainer();
- else
- containerToken = fContainer->ResolveToken(t, objectBeingExamined, objectThatCausedError);
-
- //
- // We really expect the container token to either resolve correctly
- // or fail.
- //
- ASSERT(containerToken);
- if(containerToken != nil)
- {
- //
- // If we have a cached object, get rid of it now
- //
- if(fCachedToken != nil)
- {
- ((TObjectSpecifier*)this)->fCachedToken->DisposeDesignator();
- ((TObjectSpecifier*)this)->fCachedToken = nil;
- }
-
- //
- // Try to resolve this object specifier
- //
- Try
- {
- ((TObjectSpecifier*)this)->fCachedToken = containerToken->Access(t, fDesiredClass, fKeyForm, fKeyData);
- if(fCachedToken == nil)
- FailErr(errAENoSuchObject);
- }
- Catch(err)
- {
- if(objectThatCausedError && objectThatCausedError->IsNullDescriptor())
- {
- *objectThatCausedError = this->BuildObjectSpecifier();
- }
- Throw(err);
- }
- ((TObjectSpecifier*)this)->fCachedObjectBeingExamined = objectBeingExamined;
- containerToken->DisposeDesignator();
- }
- }
-
- //
- // Return a copy of the cached token
- //
- TAbstractScriptableObject* result = fCachedToken ? fCachedToken->CloneDesignator() : nil;
-
- return result;
- } // TObjectSpecifier::ResolveToken
-
- //========================================================================================
- // Class TObjectBeingExamined
- //========================================================================================
-
- //----------------------------------------------------------------------------------------
- // TObjectBeingExamined::KeyForm
- //----------------------------------------------------------------------------------------
- DescType TObjectBeingExamined::KeyForm() const
- {
- //
- // Special flag to identify a TObjectBeingExamined
- //
- return typeObjectBeingExamined;
- }
-
- //----------------------------------------------------------------------------------------
- // TObjectBeingExamined::RootContainerIsObjectBeingExamined
- //----------------------------------------------------------------------------------------
- Boolean TObjectBeingExamined::RootContainerIsObjectBeingExamined() const
- {
- return true;
- }
-
- //----------------------------------------------------------------------------------------
- // TObjectBeingExamined::BuildObjectSpecifier
- //----------------------------------------------------------------------------------------
- TDescriptor TObjectBeingExamined::BuildObjectSpecifier() const
- {
- TDescriptor result;
-
- //
- // 'objectBeingExamined' is a special object specifier that only
- // has meaning in the context of a comparison descriptor.
- //
- result.SetDescriptorDataTypeObjectBeingExamined();
-
- return result;
- }
-
- //----------------------------------------------------------------------------------------
- // TObjectBeingExamined::ResolveToken
- //----------------------------------------------------------------------------------------
- TAbstractScriptableObject* TObjectBeingExamined::ResolveToken(const TAETransaction&, TAbstractScriptableObject* objectBeingExamined, TDescriptor* /*objectThatCausedError = nil*/) const
- {
- REQUIREVALIDPOINTER(objectBeingExamined);
- return objectBeingExamined->CloneDesignator();
- } // TObjectBeingExamined::ResolveToken
-
-
- //========================================================================================
- // Class TArbitrarySpecifier
- //========================================================================================
-
- //----------------------------------------------------------------------------------------
- // TArbitrarySpecifier::~TArbitrarySpecifier
- //----------------------------------------------------------------------------------------
- TArbitrarySpecifier::~TArbitrarySpecifier()
- {
- fKeyData.Dispose();
- } // TArbitrarySpecifier::~TArbitrarySpecifier
-
- //----------------------------------------------------------------------------------------
- // TArbitrarySpecifier::BuildObjectSpecifier
- //----------------------------------------------------------------------------------------
- TDescriptor TArbitrarySpecifier::BuildObjectSpecifier() const
- {
- TDescriptor result;
- TDescriptor nullContainer;
-
- result.MakeObjectSpecifier(typeWildCard, nullContainer, fKeyData.DescriptorType(), fKeyData, false);
-
- return result;
- } // TArbitrarySpecifier::BuildObjectSpecifier
-
- //----------------------------------------------------------------------------------------
- // TArbitrarySpecifier::ResolveToken
- //----------------------------------------------------------------------------------------
- TAbstractScriptableObject* TArbitrarySpecifier::ResolveToken(const TAETransaction& t, TAbstractScriptableObject* /*objectBeingExamined*/, TDescriptor* objectThatCausedError /*= nil*/) const
- {
- TAbstractScriptableObject* result = nil;
- OSErr err = noErr;
-
- //
- // If we attempt to resolve a descriptor that is NOT an object
- // specifier, then we will pass it to the null container's
- // access method, using:
- //
- // desired class = typeWildCard
- // key form = descriptor type of the descriptor being resolved
- // key data = the descriptor being resolved
- //
- // If the descriptor type is unknown, then the null container
- // will no doubt return errAEBadKeyForm.
- //
- TAbstractScriptableObject* nullContainer = GetNullContainer();
- Try
- {
- result = nullContainer->Access(t, typeWildCard, fKeyData.DescriptorType(), fKeyData);
- }
- Catch(err)
- {
- if(objectThatCausedError && objectThatCausedError->IsNullDescriptor())
- {
- objectThatCausedError->SetDescriptorData(fKeyData);
- }
- nullContainer->DisposeDesignator();
- Throw(err);
- }
- nullContainer->DisposeDesignator();
-
- return result;
- } // TArbitrarySpecifier::ResolveToken
-
-